const gulp = require('gulp');
const browserSync = require('browser-sync').create();
const reload = browserSync.reload;
const plumber = require('gulp-plumber');
const path = require('path');
const chokidar = require('chokidar');

const del = require('del');
const pug = require('gulp-pug');
const sass = require('gulp-sass');
const babel = require('gulp-babel');

const rev = require('gulp-rev');
const revReplace = require('gulp-rev-replace');
const htmlmin = require('gulp-htmlmin');
const base64 = require('gulp-base64');
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');
const uglify = require('gulp-uglify');
const imagemin = require('gulp-imagemin');
const mozjpeg = require('imagemin-mozjpeg');
const pngquant = require('imagemin-pngquant');

const tempPath = 'node_modules/__temp__';
const srcPath = 'src';
const htmlminConfig = {
    removeComments: true,
    collapseWhitespace: true,
    minifyJS: true,
    minifyCSS: true
};
const pugSrc = [`${srcPath}/**/*.pug`, `!${srcPath}/**/_*.pug`, `!${srcPath}/lib/**/*.pug`];
const sassSrc = [`${srcPath}/**/*.sass`, `!${srcPath}/**/_*.sass`, `!${srcPath}/lib/**/*.sass`];
const jsSrc = [`${srcPath}/**/*.js`, `!${srcPath}/**/_*.js`, `!${srcPath}/lib/**/*.js`];

const dev_del = done => {
  del.sync(path.resolve(__dirname, tempPath));
  done();
};

const dev_pug = () => gulp.src(pugSrc)
  .pipe(plumber())
  .pipe(pug({ pretty: true }))
  .pipe(gulp.dest(tempPath));

const dev_sass = () => gulp.src(sassSrc)
  .pipe(plumber())
  .pipe(sass({ outputStyle: 'expanded' }).on('error', sass.logError))
  .pipe(gulp.dest(tempPath));

const dev_babel = () => gulp.src(jsSrc)
  .pipe(plumber())
  .pipe(babel())
  .pipe(gulp.dest(tempPath));

const dev_last = done => {
    browserSync.init({
        server: {
            baseDir: [tempPath, srcPath],
        },
        port: 9000,
        online: false
    });

    chokidar.watch(tempPath, {
        ignoreInitial: true,
        ignorePermissionErrors: true
    }).on('all', (event, filePath) => {
        console.log('【dev】', event, filePath);
        reload();
    });

    chokidar.watch(srcPath, {
        ignoreInitial: true,
        ignorePermissionErrors: true
    }).on('all', (event, filePath) => {
        let task;
        let deleteFilePath;
        try {
            console.log('【src】', event, path.resolve(__dirname, filePath))
            if (event === 'change' || event === 'add') {
                if (/\.pug$/.test(filePath)) {
                    task = dev_pug;
                } else if (/\.sass$/.test(filePath)) {
                    task = dev_sass;
                } else if (/\.js$/.test(filePath)) {
                    task = dev_babel;
                }
                if (!task) return;
                if (event === 'change') {
                    task();
                } else {
                    setTimeout(() => {
                        task();
                    }, 100);
                }
            } else if (event === 'unlink' || event === 'unlinkDir') {
                if (event === 'unlink') {
                    deleteFilePath = filePath.replace(/\.sass$/, '.css');
                    deleteFilePath = deleteFilePath.replace(/\.pug$/, '.html');
                } else {
                    deleteFilePath = filePath;
                }
                deleteFilePath = path.resolve(__dirname, deleteFilePath.replace(srcPath, tempPath));
                console.log('deleteFilePath: ', deleteFilePath);
                del.sync(deleteFilePath);
                reload();
            }
        } catch (err) {
            console.log('chokidar事件错误: ', err);
        }
    });
    done();
};

gulp.task('dev', gulp.series(dev_del, gulp.parallel(dev_pug, dev_sass, dev_babel), dev_last));


const build_del = done => {
  del.sync(['dist', 'rev-manifest/*.json']);
  done();
};

const build_lib = () => gulp.src(`${srcPath}/lib/**/*.*`).pipe(gulp.dest('dist/lib'));

const build_html = () => gulp.src(pugSrc)
  .pipe(pug({ pretty: true }))
  .pipe(htmlmin(htmlminConfig))
  .pipe(revReplace({ manifest: gulp.src('rev-manifest/rev-manifest-js.json') }))
  .pipe(revReplace({ manifest: gulp.src('rev-manifest/rev-manifest-css.json') }))
  .pipe(gulp.dest('dist'));

const build_css = () => gulp.src(sassSrc)
  .pipe(sass({ outputStyle: 'expanded' }).on('error', sass.logError))
  .pipe(base64({ maxImageSize: 4 * 1024 }))
  .pipe(autoprefixer({ cascade: false }))
  .pipe(cleanCSS())
  .pipe(rev())
  .pipe(gulp.dest('dist'))
  .pipe(rev.manifest('rev-manifest-css.json'))
  .pipe(gulp.dest('rev-manifest'));

const build_js = () => gulp.src(jsSrc)
  .pipe(babel())
  .pipe(uglify())
  .pipe(rev())
  .pipe(gulp.dest('dist'))
  .pipe(rev.manifest('rev-manifest-js.json'))
  .pipe(gulp.dest('rev-manifest'));

const build_img = () => gulp.src([`${srcPath}/**/*.{jpg,png}`, `!${srcPath}/lib/**/*.{jpg,png}`])
  .pipe(imagemin([mozjpeg({ quality: 80 }), pngquant({ quality: [0.6, 0.8] })]))
  .pipe(gulp.dest('dist'));

const build_test = done => {
  browserSync.init({
    server: {
      baseDir: ['dist']
    },
    port: 8888,
    online: false
  });
  done();
};

gulp.task('build', gulp.series(build_del, gulp.parallel(build_lib, build_css, build_js), build_html, build_img));
gulp.task('test', build_test);
